/*
 * makemove.c
 *
 *  Created on: Apr 13, 2013
 *      Author: locpx
 */
#include "protos.h"
#include "extglobals.h"
#include "string.h"
#include "move.h"

// makeMove function used for "move <moveText>" command
void makeMove(MOVE move)
{
	unsigned int from = getFrom(move);
	unsigned int to = getTosq(move);
	unsigned int piece = getPiec(move);
	unsigned int captured = getCapt(move);

	BITBOARD fromBitBoard  = BITBOARDSET[from];
	BITBOARD fromToBitBoard = orTwoBitBoards(fromBitBoard, BITBOARDSET[to]);

	board.gameLine[board.endOfSearch].move.moveInt = move.moveInt;
	board.endOfSearch++;

	board.square[from] = EMPTY;

	switch (piece)
	{
	case 1: // white pawn
		board.square[to] = WHITE_PAWN;
		board.whitePawns = xorTwoBitBoards(board.whitePawns, fromToBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, fromToBitBoard);
		break;

	case 2: // white king
		board.square[to] = WHITE_KING;
		board.whiteKing = xorTwoBitBoards(board.whiteKing, fromToBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, fromToBitBoard);
		break;

	case 3: // white advisor
		board.square[to] = WHITE_ADVISOR;
		board.whiteAdvisors = xorTwoBitBoards(board.whiteAdvisors, fromToBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, fromToBitBoard);
		break;

	case 4: // white elephant
		board.square[to] = WHITE_ELEPHANT;
		board.whiteElephants = xorTwoBitBoards(board.whiteElephants, fromToBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, fromToBitBoard);
		break;

	case 5: // white rook
		board.square[to] = WHITE_ROOK;
		board.whiteRooks = xorTwoBitBoards(board.whiteRooks, fromToBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, fromToBitBoard);
		break;

	case 6: // white cannon
		board.square[to] = WHITE_CANNON;
		board.whiteCannons = xorTwoBitBoards(board.whiteCannons, fromToBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, fromToBitBoard);
		break;

	case 7: // white horse
		board.square[to] = WHITE_HORSE;
		board.whiteHorses = xorTwoBitBoards(board.whiteHorses, fromToBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, fromToBitBoard);
		break;

	case 8: // black pawn
		board.square[to] = BLACK_PAWN;
		board.blackPawns = xorTwoBitBoards(board.blackPawns, fromToBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, fromToBitBoard);
		break;

	case 9: // black king
		board.square[to] = BLACK_KING;
		board.blackKing = xorTwoBitBoards(board.blackKing, fromToBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, fromToBitBoard);
		break;

	case 10: // black advisor
		board.square[to] = BLACK_ADVISOR;
		board.blackAdvisors = xorTwoBitBoards(board.blackAdvisors, fromToBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, fromToBitBoard);
		break;

	case 11: // black elephant
		board.square[to] = BLACK_ELEPHANT;
		board.blackElephants = xorTwoBitBoards(board.blackElephants, fromToBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, fromToBitBoard);
		break;

	case 12: // black rook
		board.square[to] = BLACK_ROOK;
		board.blackRooks = xorTwoBitBoards(board.blackRooks, fromToBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, fromToBitBoard);
		break;

	case 13: // black cannon
		board.square[to] = BLACK_CANNON;
		board.blackCannons = xorTwoBitBoards(board.blackCannons, fromToBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, fromToBitBoard);
		break;

	case 14: // black horse
		board.square[to] = BLACK_HORSE;
		board.blackHorses = xorTwoBitBoards(board.blackHorses, fromToBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, fromToBitBoard);
		break;
	}

	if (captured)
	{
		makeCapture(captured, to);
		board.occupiedSquares = xorTwoBitBoards(board.occupiedSquares, fromBitBoard);
	}
	else
		board.occupiedSquares = xorTwoBitBoards(board.occupiedSquares, fromToBitBoard);

	board.nextMove = !board.nextMove;
}

// unMakeMove function used for "undo" command
void unMakeMove(MOVE move)
{
	unsigned int piece = getPiec(move);
	unsigned int captured = getCapt(move);
	unsigned int from = getFrom(move);
	unsigned int to = getTosq(move);

	BITBOARD fromBitBoard  = BITBOARDSET[from];
	BITBOARD fromToBitBoard = orTwoBitBoards(fromBitBoard, BITBOARDSET[to]);

	board.square[to] = EMPTY;

	switch (piece)
	{
	case 1: // white pawn:
		board.whitePawns = xorTwoBitBoards(board.whitePawns, fromToBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, fromToBitBoard);
		board.square[from] = WHITE_PAWN;
		break;

	case 2: // white king:
		board.whiteKing = xorTwoBitBoards(board.whiteKing, fromToBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, fromToBitBoard);
		board.square[from] = WHITE_KING;
		break;

	case 3: // white advisor:
		board.whiteAdvisors = xorTwoBitBoards(board.whiteAdvisors, fromToBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, fromToBitBoard);
		board.square[from] = WHITE_ADVISOR;
		break;

	case 4: // white elephant:
		board.whiteElephants = xorTwoBitBoards(board.whiteElephants, fromToBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, fromToBitBoard);
		board.square[from] = WHITE_ELEPHANT;
		break;

	case 5: // white rook:
		board.whiteRooks = xorTwoBitBoards(board.whiteRooks, fromToBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, fromToBitBoard);
		board.square[from] = WHITE_ROOK;
		break;

	case 6: // white cannon:
		board.whiteCannons = xorTwoBitBoards(board.whiteCannons, fromToBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, fromToBitBoard);
		board.square[from] = WHITE_CANNON;
		break;

	case 7: // white horse:
		board.whiteHorses = xorTwoBitBoards(board.whiteHorses, fromToBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, fromToBitBoard);
		board.square[from] = WHITE_HORSE;
		break;

	case 8: // black pawn:
		board.blackPawns = xorTwoBitBoards(board.blackPawns, fromToBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, fromToBitBoard);
		board.square[from] = BLACK_PAWN;
		break;

	case 9: // black king:
		board.blackKing = xorTwoBitBoards(board.blackKing, fromToBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, fromToBitBoard);
		board.square[from] = BLACK_KING;
		break;

	case 10: // black advisor:
		board.blackAdvisors = xorTwoBitBoards(board.blackAdvisors, fromToBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, fromToBitBoard);
		board.square[from] = BLACK_ADVISOR;
		break;

	case 11: // black elephant:
		board.blackElephants = xorTwoBitBoards(board.blackElephants, fromToBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, fromToBitBoard);
		board.square[from] = BLACK_ELEPHANT;
		break;

	case 12: // black rook:
		board.blackRooks = xorTwoBitBoards(board.blackRooks, fromToBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, fromToBitBoard);
		board.square[from] = BLACK_ROOK;
		break;

	case 13: // black cannon:
		board.blackCannons = xorTwoBitBoards(board.blackCannons, fromToBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, fromToBitBoard);
		board.square[from] = BLACK_CANNON;
		break;

	case 14: // black horse:
		board.blackHorses = xorTwoBitBoards(board.blackHorses, fromToBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, fromToBitBoard);
		board.square[from] = BLACK_HORSE;
		break;
	}

	if (captured)
	{
		unMakeCapture(captured, to);
		board.occupiedSquares = xorTwoBitBoards(board.occupiedSquares, fromBitBoard);
	}
	else
		board.occupiedSquares = xorTwoBitBoards(board.occupiedSquares, fromToBitBoard);

	board.endOfSearch--;

	board.nextMove = !board.nextMove;
}

void makeCapture(unsigned int captured, unsigned int to)
{
	// deals with all captures
	BITBOARD toBitBoard = BITBOARDSET[to];

	switch (captured)
	{
	case 1: // white pawn
		board.whitePawns = xorTwoBitBoards(board.whitePawns, toBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, toBitBoard);
		break;

	case 2: // white king
		board.whiteKing = xorTwoBitBoards(board.whiteKing, toBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, toBitBoard);
		break;

	case 3: // white advisor
		board.whiteAdvisors = xorTwoBitBoards(board.whiteAdvisors, toBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, toBitBoard);
		break;

	case 4: // white elephant
		board.whiteElephants = xorTwoBitBoards(board.whiteElephants, toBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, toBitBoard);
		break;

	case 5: // white rook
		board.whiteRooks = xorTwoBitBoards(board.whiteRooks, toBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, toBitBoard);
		break;

	case 6: // white cannon
		board.whiteCannons = xorTwoBitBoards(board.whiteCannons, toBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, toBitBoard);
		break;

	case 7: // white horse
		board.whiteHorses = xorTwoBitBoards(board.whiteHorses, toBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, toBitBoard);
		break;

	case 8: // black pawn
		board.blackPawns = xorTwoBitBoards(board.blackPawns, toBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, toBitBoard);
		break;

	case 9: // black king
		board.blackKing = xorTwoBitBoards(board.blackKing, toBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, toBitBoard);
		break;

	case 10: // black advisor
		board.blackAdvisors = xorTwoBitBoards(board.blackAdvisors, toBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, toBitBoard);
		break;

	case 11: // black elephant
		board.blackElephants = xorTwoBitBoards(board.blackElephants, toBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, toBitBoard);
		break;

	case 12: // black rook
		board.blackRooks = xorTwoBitBoards(board.blackRooks, toBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, toBitBoard);
		break;

	case 13: // black cannon
		board.blackCannons = xorTwoBitBoards(board.blackCannons, toBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, toBitBoard);
		break;

	case 14: // black horse
		board.blackHorses = xorTwoBitBoards(board.blackHorses, toBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, toBitBoard);
		break;
	}
}

void unMakeCapture(unsigned int captured, unsigned int to)
{
	// deals with all captures
	BITBOARD toBitBoard = BITBOARDSET[to];

	switch (captured)
	{
	case 1: // white pawn:
		board.whitePawns = xorTwoBitBoards(board.whitePawns, toBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, toBitBoard);
		board.square[to] = WHITE_PAWN;
		break;

	case 2: // white king:
		board.whiteKing = xorTwoBitBoards(board.whiteKing, toBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, toBitBoard);
		board.square[to] = WHITE_KING;
		break;

	case 3: // white advisor:
		board.whiteAdvisors = xorTwoBitBoards(board.whiteAdvisors, toBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, toBitBoard);
		board.square[to] = WHITE_ADVISOR;
		break;

	case 4: // white elephant:
		board.whiteElephants = xorTwoBitBoards(board.whiteElephants, toBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, toBitBoard);
		board.square[to] = WHITE_ELEPHANT;
		break;

	case 5: // white rook:
		board.whiteRooks = xorTwoBitBoards(board.whiteRooks, toBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, toBitBoard);
		board.square[to] = WHITE_ROOK;
		break;

	case 6: // white cannon:
		board.whiteCannons = xorTwoBitBoards(board.whiteCannons, toBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, toBitBoard);
		board.square[to] = WHITE_CANNON;
		break;

	case 7: // white horse:
		board.whiteHorses = xorTwoBitBoards(board.whiteHorses, toBitBoard);
		board.whitePieces = xorTwoBitBoards(board.whitePieces, toBitBoard);
		board.square[to] = WHITE_HORSE;
		break;

	case 8: // black pawn:
		board.blackPawns = xorTwoBitBoards(board.blackPawns, toBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, toBitBoard);
		board.square[to] = BLACK_PAWN;
		break;

	case 9: // black king:
		board.blackKing = xorTwoBitBoards(board.blackKing, toBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, toBitBoard);
		board.square[to] = BLACK_KING;
		break;

	case 10: // black advisor:
		board.blackAdvisors = xorTwoBitBoards(board.blackAdvisors, toBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, toBitBoard);
		board.square[to] = BLACK_ADVISOR;
		break;

	case 11: // black elephant:
		board.blackElephants = xorTwoBitBoards(board.blackElephants, toBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, toBitBoard);
		board.square[to] = BLACK_ELEPHANT;
		break;

	case 12: // black rook:
		board.blackRooks = xorTwoBitBoards(board.blackRooks, toBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, toBitBoard);
		board.square[to] = BLACK_ROOK;
		break;

	case 13: // black cannon:
		board.blackCannons = xorTwoBitBoards(board.blackCannons, toBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, toBitBoard);
		board.square[to] = BLACK_CANNON;
		break;

	case 14: // black horse:
		board.blackHorses = xorTwoBitBoards(board.blackHorses, toBitBoard);
		board.blackPieces = xorTwoBitBoards(board.blackPieces, toBitBoard);
		board.square[to] = BLACK_HORSE;
		break;
	}
}

BOOL isValidTextMove(char *userMove, MOVE *move)
{
	// Checks if userMove is valid by comparing it with moves from the move generator
	// If found valid, the move is returned

	unsigned char userFrom, userTo;
	int i;

	if (strlen(userMove) < 4)
	{
		move->moveInt = 0;
		return FALSE;
	}

	userFrom = userMove[0] - 97;
	userFrom += 9 * (userMove[1] - 48);
	userTo = userMove[2] - 97;
	userTo += 9 * (userMove[3] - 48);

	if (userFrom == userTo)
	{
		move->moveInt = 0;
		return FALSE;
	}

	for (i = board.moveBufLen[0]; i < board.moveBufLen[1]; i++)
	{
		if ((getFrom(board.moveBuffer[i]) == userFrom) && (getTosq(board.moveBuffer[i]) == userTo))
		{
			move->moveInt = board.moveBuffer[i].moveInt;
			return TRUE;
		}
	}

	move->moveInt = 0;
	return FALSE;
}

BOOL isOtherKingAttacked()
{
	// check to see if we are leaving our king in check
	if (board.nextMove)
	{
		return isAttacked(board.whiteKing, board.nextMove);
	}
	else
	{
		return isAttacked(board.blackKing, board.nextMove);
	}
}

BOOL isTwoKingsFaceToFace()
{
	// check if white king and black king face to face
	// kings are not allowed to face each other directly. That is, if the two kings are on the same file,
	// at least one piece from either side must be in between, also on this file. A king will be captured if it moves into
	// the “line of sight” of the other king
	unsigned int whiteFrom = findFirstOneInBitBoard(board.whiteKing);
	unsigned int blackFrom = findFirstOneInBitBoard(board.blackKing);

	// the two kings are on the same file
	if (FILES[whiteFrom] == FILES[blackFrom])
	{
		BITBOARD whiteKingAttacks = ATTACKS_TOP[whiteFrom];
		BITBOARD blackKingAttacks = ATTACKS_BOTTOM[blackFrom];

		// The BITBOARD that all squares between two kings on the same file are set
		BITBOARD betweenTwoKings = andTwoBitBoards(whiteKingAttacks, blackKingAttacks);

		// no piece is between the two kings
		if (isAllZeroBit(andTwoBitBoards(betweenTwoKings, board.occupiedSquares)))
				return TRUE;
	}

	return FALSE;
}

BOOL isAttacked(BITBOARD targetBitBoard, unsigned char fromSide)
{

	//  ===========================================================================
	//  isAttacked is used mainly as a move legality test to see if targetBitBoard is
	//  attacked by white or black.
	//  Returns true at the first attack found, and returns false if no attack is found.
	//  ===========================================================================

	int toSquare;
	BITBOARD tempTargetBitBoard = targetBitBoard;
	BITBOARD tempPiece, tempMove;
	int from, to;

	if (fromSide) // test for attacks from BLACK to targetBitBoard
	{
		while (!isAllZeroBit(tempTargetBitBoard))
		{
			toSquare = findFirstOneInBitBoard(tempTargetBitBoard);

			// there's at least a black pawn can attack to toSqure
			if (!isAllZeroBit(andTwoBitBoards(board.blackPawns, BLACK_PAWN_ATTACKS[toSquare]))) return TRUE;

			// there's at least a black advisor can attack to toSqure
			if (!isAllZeroBit(andTwoBitBoards(board.blackAdvisors, ADVISOR_ATTACKS[toSquare]))) return TRUE;

			//the black king can attack to toSqure
			if (!isAllZeroBit(andTwoBitBoards(board.blackKing, KING_ATTACKS[toSquare]))) return TRUE;

			// Check if there is any black horses can attack to toSqure
			tempPiece = board.blackHorses;
			while (!isAllZeroBit(tempPiece))
			{
				from = findFirstOneInBitBoard(tempPiece);

				clearBitBoard(&tempMove);
				if (isAllZeroBit(andTwoBitBoards(board.occupiedSquares, HORSE_OBSTRUCTS[from][0])))
					tempMove = orTwoBitBoards(tempMove, HORSE_ATTACKS[from][0]);
				if (isAllZeroBit(andTwoBitBoards(board.occupiedSquares, HORSE_OBSTRUCTS[from][1])))
					tempMove = orTwoBitBoards(tempMove, HORSE_ATTACKS[from][1]);
				if (isAllZeroBit(andTwoBitBoards(board.occupiedSquares, HORSE_OBSTRUCTS[from][2])))
					tempMove = orTwoBitBoards(tempMove, HORSE_ATTACKS[from][2]);
				if (isAllZeroBit(andTwoBitBoards(board.occupiedSquares, HORSE_OBSTRUCTS[from][3])))
					tempMove = orTwoBitBoards(tempMove, HORSE_ATTACKS[from][3]);

				tempMove = andTwoBitBoards(tempMove, tempTargetBitBoard);
				while (!isAllZeroBit(tempMove))
				{
					to = findFirstOneInBitBoard(tempMove);
					if (to == toSquare)
						return TRUE;
					tempMove = xorTwoBitBoards(tempMove, BITBOARDSET[to]);
				}
				tempPiece = xorTwoBitBoards(tempPiece, BITBOARDSET[from]);
			}

			// Check if there is any black elephants can attack to toSqure
			tempPiece = board.blackElephants;
			while (!isAllZeroBit(tempPiece))
			{
				from = findFirstOneInBitBoard(tempPiece);
				clearBitBoard(&tempMove);
				if (isAllZeroBit(andTwoBitBoards(board.occupiedSquares, ELEPHANT_OBSTRUCTS[from][0])))
					tempMove = orTwoBitBoards(tempMove, ELEPHANT_ATTACKS[from][0]);
				if (isAllZeroBit(andTwoBitBoards(board.occupiedSquares, ELEPHANT_OBSTRUCTS[from][1])))
					tempMove = orTwoBitBoards(tempMove, ELEPHANT_ATTACKS[from][1]);
				if (isAllZeroBit(andTwoBitBoards(board.occupiedSquares, ELEPHANT_OBSTRUCTS[from][2])))
					tempMove = orTwoBitBoards(tempMove, ELEPHANT_ATTACKS[from][2]);
				if (isAllZeroBit(andTwoBitBoards(board.occupiedSquares, ELEPHANT_OBSTRUCTS[from][3])))
					tempMove = orTwoBitBoards(tempMove, ELEPHANT_ATTACKS[from][3]);
				tempMove = andTwoBitBoards(tempMove, tempTargetBitBoard);
				while (!isAllZeroBit(tempMove))
				{
					to = findFirstOneInBitBoard(tempMove);
					if (to == toSquare)
						return TRUE;
					tempMove = xorTwoBitBoards(tempMove, BITBOARDSET[to]);
				}
				tempPiece = xorTwoBitBoards(tempPiece, BITBOARDSET[from]);
			}

			// Check if there is any black rooks can attack to toSqure
			BITBOARD rookAttacks, rookRightAttacks, rookTopAttacks, rookLeftAttacks, rookBottomAttacks;
			tempPiece = board.blackRooks;
			while (!isAllZeroBit(tempPiece))
			{
				from = findFirstOneInBitBoard(tempPiece);

				// We do this because the first piece will stop the rook moving to the right.
				rookRightAttacks = andTwoBitBoards(ATTACKS_RIGHT[from], board.occupiedSquares);
				// Because the first piece will stop the rook, we need to fill in all the squares to the right of the piece
				if (!isAllZeroBit(rookRightAttacks))
					rookRightAttacks = ATTACKS_RIGHT[findFirstOneInBitBoard(rookRightAttacks)];
				// To get the squares where the rook can move to, we exclusive OR the board with ATTACKS_RIGHT[from]
				rookRightAttacks = xorTwoBitBoards(rookRightAttacks, ATTACKS_RIGHT[from]);

				// We do this because the first piece will stop the rook moving on the top.
				rookTopAttacks = andTwoBitBoards(ATTACKS_TOP[from], board.occupiedSquares);
				// Because the first piece will stop the rook, we need to fill in all the squares on the top of the piece
				if (!isAllZeroBit(rookTopAttacks))
					rookTopAttacks = ATTACKS_TOP[findFirstOneInBitBoard(rookTopAttacks)];
				// To get the squares where the rook can move to, we exclusive OR the board with ATTACKS_TOP[from]
				rookTopAttacks = xorTwoBitBoards(rookTopAttacks, ATTACKS_TOP[from]);

				// We do this because the first piece will stop the rook moving to the left.
				rookLeftAttacks = andTwoBitBoards(ATTACKS_LEFT[from], board.occupiedSquares);
				// Because the first piece will stop the rook, we need to fill in all the squares to the left of the piece
				if (!isAllZeroBit(rookLeftAttacks))
					rookLeftAttacks = ATTACKS_LEFT[findLastOneInBitBoard(rookLeftAttacks)];
				// To get the squares where the rook can move to, we exclusive OR the board with ATTACKS_LEFT[from]
				rookLeftAttacks = xorTwoBitBoards(rookLeftAttacks, ATTACKS_LEFT[from]);

				// We do this because the first piece will stop the rook moving on the bottom.
				rookBottomAttacks = andTwoBitBoards(ATTACKS_BOTTOM[from], board.occupiedSquares);
				// Because the first piece will stop the rook, we need to fill in all the squares on the bottom of the piece
				if (!isAllZeroBit(rookBottomAttacks))
					rookBottomAttacks = ATTACKS_BOTTOM[findLastOneInBitBoard(rookBottomAttacks)];
				// To get the squares where the rook can move to, we exclusive OR the board with ATTACKS_BOTTOM[from]
				rookBottomAttacks = xorTwoBitBoards(rookBottomAttacks, ATTACKS_BOTTOM[from]);

				rookAttacks = orTwoBitBoards(rookRightAttacks, rookTopAttacks);
				rookAttacks = orTwoBitBoards(rookAttacks, rookLeftAttacks);
				rookAttacks = orTwoBitBoards(rookAttacks, rookBottomAttacks);

				tempMove = andTwoBitBoards(rookAttacks, tempTargetBitBoard);
				while (!isAllZeroBit(tempMove))
				{
					to = findFirstOneInBitBoard(tempMove);
					if (to == toSquare)
						return TRUE;
					tempMove = xorTwoBitBoards(tempMove, BITBOARDSET[to]);
				}
				tempPiece = xorTwoBitBoards(tempPiece, BITBOARDSET[from]);
			}

			// Check if there is any black cannons can attack to toSqure
			BITBOARD cannonAttacks, cannonRightAttacks, cannonTopAttacks, cannonLeftAttacks, cannonBottomAttacks;
			BITBOARD rightTempBB, topTempBB, leftTempBB, bottomTempBB;
			tempPiece = board.blackCannons;
			while (!isAllZeroBit(tempPiece))
			{
				from = findFirstOneInBitBoard(tempPiece);

				clearBitBoard(&rightTempBB);
				clearBitBoard(&topTempBB);
				clearBitBoard(&leftTempBB);
				clearBitBoard(&bottomTempBB);

				// We do this because the first piece will stop the rook moving to the right.
				cannonRightAttacks = andTwoBitBoards(ATTACKS_RIGHT[from], board.occupiedSquares);
				// Because the first piece will stop the cannon, we need to fill in all the squares to the right of the piece
				if (!isAllZeroBit(cannonRightAttacks))
				{
					unsigned int firstOne = findFirstOneInBitBoard(cannonRightAttacks);
					cannonRightAttacks = ATTACKS_RIGHT[firstOne];
					cannonRightAttacks = orTwoBitBoards(cannonRightAttacks, BITBOARDSET[firstOne]);

					rightTempBB = andTwoBitBoards(ATTACKS_RIGHT[firstOne], board.whitePieces);
					if (!isAllZeroBit(rightTempBB))
						rightTempBB = BITBOARDSET[findFirstOneInBitBoard(rightTempBB)];
				}
				// To get the squares where the cannon can move to, we exclusive OR the board with ATTACKS_RIGHT[from]
				cannonRightAttacks = xorTwoBitBoards(cannonRightAttacks, ATTACKS_RIGHT[from]);
				// Eat if possible
				cannonRightAttacks = orTwoBitBoards(cannonRightAttacks, rightTempBB);


				// We do this because the first piece will stop the cannon moving on the top.
				cannonTopAttacks = andTwoBitBoards(ATTACKS_TOP[from], board.occupiedSquares);
				// Because the first piece will stop the cannon, we need to fill in all the squares on the top of the piece
				if (!isAllZeroBit(cannonTopAttacks))
				{
					unsigned int firstOne = findFirstOneInBitBoard(cannonTopAttacks);
					cannonTopAttacks = ATTACKS_TOP[firstOne];
					cannonTopAttacks = orTwoBitBoards(cannonTopAttacks, BITBOARDSET[firstOne]);

					topTempBB = andTwoBitBoards(ATTACKS_TOP[firstOne], board.whitePieces);
					if (!isAllZeroBit(topTempBB))
						topTempBB = BITBOARDSET[findFirstOneInBitBoard(topTempBB)];
				}
				// To get the squares where the cannon can move to, we exclusive OR the board with ATTACKS_TOP[from]
				cannonTopAttacks = xorTwoBitBoards(cannonTopAttacks, ATTACKS_TOP[from]);
				// Eat if possible
				cannonTopAttacks = orTwoBitBoards(cannonTopAttacks, topTempBB);


				// We do this because the first piece will stop the cannon moving to the left.
				cannonLeftAttacks = andTwoBitBoards(ATTACKS_LEFT[from], board.occupiedSquares);
				// Because the first piece will stop the cannon, we need to fill in all the squares to the left of the piece
				if (!isAllZeroBit(cannonLeftAttacks))
				{
					unsigned int lastOne = findLastOneInBitBoard(cannonLeftAttacks);
					cannonLeftAttacks = ATTACKS_LEFT[lastOne];
					cannonLeftAttacks = orTwoBitBoards(cannonLeftAttacks, BITBOARDSET[lastOne]);

					leftTempBB = andTwoBitBoards(ATTACKS_LEFT[lastOne], board.whitePieces);
					if (!isAllZeroBit(leftTempBB))
						leftTempBB = BITBOARDSET[findLastOneInBitBoard(leftTempBB)];
				}
				// To get the squares where the cannon can move to, we exclusive OR the board with ATTACKS_LEFT[from]
				cannonLeftAttacks = xorTwoBitBoards(cannonLeftAttacks, ATTACKS_LEFT[from]);
				// Eat if possible
				cannonLeftAttacks = orTwoBitBoards(cannonLeftAttacks, leftTempBB);


				// We do this because the first piece will stop the cannon moving on the bottom.
				cannonBottomAttacks = andTwoBitBoards(ATTACKS_BOTTOM[from], board.occupiedSquares);
				// Because the first piece will stop the cannon, we need to fill in all the squares on the bottom of the piece
				if (!isAllZeroBit(cannonBottomAttacks))
				{
					unsigned int lastOne = findLastOneInBitBoard(cannonBottomAttacks);
					cannonBottomAttacks = ATTACKS_BOTTOM[lastOne];
					cannonBottomAttacks = orTwoBitBoards(cannonBottomAttacks, BITBOARDSET[lastOne]);

					bottomTempBB = andTwoBitBoards(ATTACKS_BOTTOM[lastOne], board.whitePieces);
					if (!isAllZeroBit(bottomTempBB))
						bottomTempBB = BITBOARDSET[findLastOneInBitBoard(bottomTempBB)];
				}
				// To get the squares where the cannon can move to, we exclusive OR the board with ATTACKS_BOTTOM[from]
				cannonBottomAttacks = xorTwoBitBoards(cannonBottomAttacks, ATTACKS_BOTTOM[from]);
				// Eat if possible
				cannonBottomAttacks = orTwoBitBoards(cannonBottomAttacks, bottomTempBB);

				cannonAttacks = orTwoBitBoards(cannonRightAttacks, cannonTopAttacks);
				cannonAttacks = orTwoBitBoards(cannonAttacks, cannonLeftAttacks);
				cannonAttacks = orTwoBitBoards(cannonAttacks, cannonBottomAttacks);

				tempMove = andTwoBitBoards(cannonAttacks, tempTargetBitBoard);
				while (!isAllZeroBit(tempMove))
				{
					to = findFirstOneInBitBoard(tempMove);
					if (to == toSquare)
						return TRUE;
					tempMove = xorTwoBitBoards(tempMove, BITBOARDSET[to]);
				}
				tempPiece = xorTwoBitBoards(tempPiece, BITBOARDSET[from]);
			}

			tempTargetBitBoard = xorTwoBitBoards(tempTargetBitBoard, BITBOARDSET[toSquare]);
		}
	}
	else // test for attacks from WHITE to targetBitmap
	{
		while (!isAllZeroBit(tempTargetBitBoard))
		{
			toSquare = findFirstOneInBitBoard(tempTargetBitBoard);

			// there's at least a white pawn can attack to toSqure
			if (!isAllZeroBit(andTwoBitBoards(board.whitePawns, WHITE_PAWN_ATTACKS[toSquare]))) return TRUE;

			// there's at least a white advisor can attack to toSqure
			if (!isAllZeroBit(andTwoBitBoards(board.whiteAdvisors, ADVISOR_ATTACKS[toSquare]))) return TRUE;

			//the white king can attack to toSqure
			if (!isAllZeroBit(andTwoBitBoards(board.whiteKing, KING_ATTACKS[toSquare]))) return TRUE;

			// Check if there is any white horses can attack to toSqure
			tempPiece = board.whiteHorses;
			while (!isAllZeroBit(tempPiece))
			{
				from = findFirstOneInBitBoard(tempPiece);

				clearBitBoard(&tempMove);
				if (isAllZeroBit(andTwoBitBoards(board.occupiedSquares, HORSE_OBSTRUCTS[from][0])))
					tempMove = orTwoBitBoards(tempMove, HORSE_ATTACKS[from][0]);
				if (isAllZeroBit(andTwoBitBoards(board.occupiedSquares, HORSE_OBSTRUCTS[from][1])))
					tempMove = orTwoBitBoards(tempMove, HORSE_ATTACKS[from][1]);
				if (isAllZeroBit(andTwoBitBoards(board.occupiedSquares, HORSE_OBSTRUCTS[from][2])))
					tempMove = orTwoBitBoards(tempMove, HORSE_ATTACKS[from][2]);
				if (isAllZeroBit(andTwoBitBoards(board.occupiedSquares, HORSE_OBSTRUCTS[from][3])))
					tempMove = orTwoBitBoards(tempMove, HORSE_ATTACKS[from][3]);

				tempMove = andTwoBitBoards(tempMove, tempTargetBitBoard);
				while (!isAllZeroBit(tempMove))
				{
					to = findFirstOneInBitBoard(tempMove);
					if (to == toSquare)
						return TRUE;
					tempMove = xorTwoBitBoards(tempMove, BITBOARDSET[to]);
				}
				tempPiece = xorTwoBitBoards(tempPiece, BITBOARDSET[from]);
			}

			// Check if there is any white elephants can attack to toSqure
			tempPiece = board.whiteElephants;
			while (!isAllZeroBit(tempPiece))
			{
				from = findFirstOneInBitBoard(tempPiece);
				clearBitBoard(&tempMove);
				if (isAllZeroBit(andTwoBitBoards(board.occupiedSquares, ELEPHANT_OBSTRUCTS[from][0])))
					tempMove = orTwoBitBoards(tempMove, ELEPHANT_ATTACKS[from][0]);
				if (isAllZeroBit(andTwoBitBoards(board.occupiedSquares, ELEPHANT_OBSTRUCTS[from][1])))
					tempMove = orTwoBitBoards(tempMove, ELEPHANT_ATTACKS[from][1]);
				if (isAllZeroBit(andTwoBitBoards(board.occupiedSquares, ELEPHANT_OBSTRUCTS[from][2])))
					tempMove = orTwoBitBoards(tempMove, ELEPHANT_ATTACKS[from][2]);
				if (isAllZeroBit(andTwoBitBoards(board.occupiedSquares, ELEPHANT_OBSTRUCTS[from][3])))
					tempMove = orTwoBitBoards(tempMove, ELEPHANT_ATTACKS[from][3]);
				tempMove = andTwoBitBoards(tempMove, tempTargetBitBoard);
				while (!isAllZeroBit(tempMove))
				{
					to = findFirstOneInBitBoard(tempMove);
					if (to == toSquare)
						return TRUE;
					tempMove = xorTwoBitBoards(tempMove, BITBOARDSET[to]);
				}
				tempPiece = xorTwoBitBoards(tempPiece, BITBOARDSET[from]);
			}

			// Check if there is any white rooks can attack to toSqure
			BITBOARD rookAttacks, rookRightAttacks, rookTopAttacks, rookLeftAttacks, rookBottomAttacks;
			tempPiece = board.whiteRooks;
			while (!isAllZeroBit(tempPiece))
			{
				from = findFirstOneInBitBoard(tempPiece);

				// We do this because the first piece will stop the rook moving to the right.
				rookRightAttacks = andTwoBitBoards(ATTACKS_RIGHT[from], board.occupiedSquares);
				// Because the first piece will stop the rook, we need to fill in all the squares to the right of the piece
				if (!isAllZeroBit(rookRightAttacks))
					rookRightAttacks = ATTACKS_RIGHT[findFirstOneInBitBoard(rookRightAttacks)];
				// To get the squares where the rook can move to, we exclusive OR the board with ATTACKS_RIGHT[from]
				rookRightAttacks = xorTwoBitBoards(rookRightAttacks, ATTACKS_RIGHT[from]);

				// We do this because the first piece will stop the rook moving on the top.
				rookTopAttacks = andTwoBitBoards(ATTACKS_TOP[from], board.occupiedSquares);
				// Because the first piece will stop the rook, we need to fill in all the squares on the top of the piece
				if (!isAllZeroBit(rookTopAttacks))
					rookTopAttacks = ATTACKS_TOP[findFirstOneInBitBoard(rookTopAttacks)];
				// To get the squares where the rook can move to, we exclusive OR the board with ATTACKS_TOP[from]
				rookTopAttacks = xorTwoBitBoards(rookTopAttacks, ATTACKS_TOP[from]);

				// We do this because the first piece will stop the rook moving to the left.
				rookLeftAttacks = andTwoBitBoards(ATTACKS_LEFT[from], board.occupiedSquares);
				// Because the first piece will stop the rook, we need to fill in all the squares to the left of the piece
				if (!isAllZeroBit(rookLeftAttacks))
					rookLeftAttacks = ATTACKS_LEFT[findLastOneInBitBoard(rookLeftAttacks)];
				// To get the squares where the rook can move to, we exclusive OR the board with ATTACKS_LEFT[from]
				rookLeftAttacks = xorTwoBitBoards(rookLeftAttacks, ATTACKS_LEFT[from]);

				// We do this because the first piece will stop the rook moving on the bottom.
				rookBottomAttacks = andTwoBitBoards(ATTACKS_BOTTOM[from], board.occupiedSquares);
				// Because the first piece will stop the rook, we need to fill in all the squares on the bottom of the piece
				if (!isAllZeroBit(rookBottomAttacks))
					rookBottomAttacks = ATTACKS_BOTTOM[findLastOneInBitBoard(rookBottomAttacks)];
				// To get the squares where the rook can move to, we exclusive OR the board with ATTACKS_BOTTOM[from]
				rookBottomAttacks = xorTwoBitBoards(rookBottomAttacks, ATTACKS_BOTTOM[from]);

				rookAttacks = orTwoBitBoards(rookRightAttacks, rookTopAttacks);
				rookAttacks = orTwoBitBoards(rookAttacks, rookLeftAttacks);
				rookAttacks = orTwoBitBoards(rookAttacks, rookBottomAttacks);

				tempMove = andTwoBitBoards(rookAttacks, tempTargetBitBoard);
				while (!isAllZeroBit(tempMove))
				{
					to = findFirstOneInBitBoard(tempMove);
					if (to == toSquare)
						return TRUE;
					tempMove = xorTwoBitBoards(tempMove, BITBOARDSET[to]);
				}
				tempPiece = xorTwoBitBoards(tempPiece, BITBOARDSET[from]);
			}

			// Check if there is any white cannons can attack to toSqure
			BITBOARD cannonAttacks, cannonRightAttacks, cannonTopAttacks, cannonLeftAttacks, cannonBottomAttacks;
			BITBOARD rightTempBB, topTempBB, leftTempBB, bottomTempBB;
			tempPiece = board.whiteCannons;
			while (!isAllZeroBit(tempPiece))
			{
				from = findFirstOneInBitBoard(tempPiece);

				clearBitBoard(&rightTempBB);
				clearBitBoard(&topTempBB);
				clearBitBoard(&leftTempBB);
				clearBitBoard(&bottomTempBB);

				// We do this because the first piece will stop the rook moving to the right.
				cannonRightAttacks = andTwoBitBoards(ATTACKS_RIGHT[from], board.occupiedSquares);
				// Because the first piece will stop the cannon, we need to fill in all the squares to the right of the piece
				if (!isAllZeroBit(cannonRightAttacks))
				{
					unsigned int firstOne = findFirstOneInBitBoard(cannonRightAttacks);
					cannonRightAttacks = ATTACKS_RIGHT[firstOne];
					cannonRightAttacks = orTwoBitBoards(cannonRightAttacks, BITBOARDSET[firstOne]);

					rightTempBB = andTwoBitBoards(ATTACKS_RIGHT[firstOne], board.blackPieces);
					if (!isAllZeroBit(rightTempBB))
						rightTempBB = BITBOARDSET[findFirstOneInBitBoard(rightTempBB)];
				}
				// To get the squares where the cannon can move to, we exclusive OR the board with ATTACKS_RIGHT[from]
				cannonRightAttacks = xorTwoBitBoards(cannonRightAttacks, ATTACKS_RIGHT[from]);
				// Eat if possible
				cannonRightAttacks = orTwoBitBoards(cannonRightAttacks, rightTempBB);


				// We do this because the first piece will stop the cannon moving on the top.
				cannonTopAttacks = andTwoBitBoards(ATTACKS_TOP[from], board.occupiedSquares);
				// Because the first piece will stop the cannon, we need to fill in all the squares on the top of the piece
				if (!isAllZeroBit(cannonTopAttacks))
				{
					unsigned int firstOne = findFirstOneInBitBoard(cannonTopAttacks);
					cannonTopAttacks = ATTACKS_TOP[firstOne];
					cannonTopAttacks = orTwoBitBoards(cannonTopAttacks, BITBOARDSET[firstOne]);

					topTempBB = andTwoBitBoards(ATTACKS_TOP[firstOne], board.blackPieces);
					if (!isAllZeroBit(topTempBB))
						topTempBB = BITBOARDSET[findFirstOneInBitBoard(topTempBB)];
				}
				// To get the squares where the cannon can move to, we exclusive OR the board with ATTACKS_TOP[from]
				cannonTopAttacks = xorTwoBitBoards(cannonTopAttacks, ATTACKS_TOP[from]);
				// Eat if possible
				cannonTopAttacks = orTwoBitBoards(cannonTopAttacks, topTempBB);


				// We do this because the first piece will stop the cannon moving to the left.
				cannonLeftAttacks = andTwoBitBoards(ATTACKS_LEFT[from], board.occupiedSquares);
				// Because the first piece will stop the cannon, we need to fill in all the squares to the left of the piece
				if (!isAllZeroBit(cannonLeftAttacks))
				{
					unsigned int lastOne = findLastOneInBitBoard(cannonLeftAttacks);
					cannonLeftAttacks = ATTACKS_LEFT[lastOne];
					cannonLeftAttacks = orTwoBitBoards(cannonLeftAttacks, BITBOARDSET[lastOne]);

					leftTempBB = andTwoBitBoards(ATTACKS_LEFT[lastOne], board.blackPieces);
					if (!isAllZeroBit(leftTempBB))
						leftTempBB = BITBOARDSET[findLastOneInBitBoard(leftTempBB)];
				}
				// To get the squares where the cannon can move to, we exclusive OR the board with ATTACKS_LEFT[from]
				cannonLeftAttacks = xorTwoBitBoards(cannonLeftAttacks, ATTACKS_LEFT[from]);
				// Eat if possible
				cannonLeftAttacks = orTwoBitBoards(cannonLeftAttacks, leftTempBB);


				// We do this because the first piece will stop the cannon moving on the bottom.
				cannonBottomAttacks = andTwoBitBoards(ATTACKS_BOTTOM[from], board.occupiedSquares);
				// Because the first piece will stop the cannon, we need to fill in all the squares on the bottom of the piece
				if (!isAllZeroBit(cannonBottomAttacks))
				{
					unsigned int lastOne = findLastOneInBitBoard(cannonBottomAttacks);
					cannonBottomAttacks = ATTACKS_BOTTOM[lastOne];
					cannonBottomAttacks = orTwoBitBoards(cannonBottomAttacks, BITBOARDSET[lastOne]);

					bottomTempBB = andTwoBitBoards(ATTACKS_BOTTOM[lastOne], board.blackPieces);
					if (!isAllZeroBit(bottomTempBB))
						bottomTempBB = BITBOARDSET[findLastOneInBitBoard(bottomTempBB)];
				}
				// To get the squares where the cannon can move to, we exclusive OR the board with ATTACKS_BOTTOM[from]
				cannonBottomAttacks = xorTwoBitBoards(cannonBottomAttacks, ATTACKS_BOTTOM[from]);
				// Eat if possible
				cannonBottomAttacks = orTwoBitBoards(cannonBottomAttacks, bottomTempBB);

				cannonAttacks = orTwoBitBoards(cannonRightAttacks, cannonTopAttacks);
				cannonAttacks = orTwoBitBoards(cannonAttacks, cannonLeftAttacks);
				cannonAttacks = orTwoBitBoards(cannonAttacks, cannonBottomAttacks);

				tempMove = andTwoBitBoards(cannonAttacks, tempTargetBitBoard);
				while (!isAllZeroBit(tempMove))
				{
					to = findFirstOneInBitBoard(tempMove);
					if (to == toSquare)
						return TRUE;
					tempMove = xorTwoBitBoards(tempMove, BITBOARDSET[to]);
				}
				tempPiece = xorTwoBitBoards(tempPiece, BITBOARDSET[from]);
			}

			tempTargetBitBoard = xorTwoBitBoards(tempTargetBitBoard, BITBOARDSET[toSquare]);
		}
	}

	return FALSE;
}
